home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / newsgrp / group01b.txt / 000091_icon-group-sender_Fri Jul 6 09:39:50 2001.msg < prev    next >
Internet Message Format  |  2002-01-03  |  5KB

  1. Return-Path: <icon-group-sender>
  2. Received: (from root@localhost)
  3.     by baskerville.CS.Arizona.EDU (8.11.1/8.11.1) id f66Gcbo19262
  4.     for icon-group-addresses; Fri, 6 Jul 2001 09:38:37 -0700 (MST)
  5. Message-Id: <200107061638.f66Gcbo19262@baskerville.CS.Arizona.EDU>
  6. Date: Fri, 6 Jul 2001 14:28:00 +1200 (NZST)
  7. From: "Richard A. O'Keefe" <ok@atlas.otago.ac.nz>
  8. To: art.eschenlauer@sufsys.com, icon-group@cs.arizona.edu
  9. Subject: Re:  Software testing for Icon?
  10. Errors-To: icon-group-errors@cs.arizona.edu
  11. Status: RO
  12. Content-Length: 4722
  13.  
  14.     One concern that I expect people to raise with respect to using
  15.     Icon in the "mainstream" is, "Icon cannot be trusted because it
  16.     does not typecheck arguments at compile time."
  17.  
  18. Neither does Perl.  Doesn't seem to have slowed Perl down any.
  19. Neither do TCL, Python, Smalltalk, Scheme.
  20. For that matter, NEITHER DOES JAVA, practically speaking.
  21. In effect, any time you stuff something in a collection object,
  22. you lose all compile-time information about its type.
  23. All of these languages *do* type-check arguments at run-time.
  24.  
  25. Oh yes, you can add Javascript and Visual Basic (some variables are
  26. type-checked at compile time, some are not.)
  27.  
  28. If anyone tries that argument on you, ask them whether that stops
  29. them using Java or Visual Basic.
  30.  
  31. There is another fairly major point, which is "what kind of type
  32. system are we comparing against?"  For example, can it express
  33. the following constraint I actually used today in a design:
  34.  
  35.     data Tree k v = Leaf | Node k v (Tree k v) (Tree k v)
  36.  
  37.     size :: Tree k v -> Int
  38.     size (Leaf)         = 0
  39.     size (Node _ _ l r) = size l + size r
  40.  
  41.     well_ordered :: (Ord k) => Tree k v -> Bool
  42.     well_ordered (Leaf)         = True
  43.     well_ordered (Node k _ l r) = well_ordered l && well_ordered r &&
  44.                                   all_less l && all_grtr r
  45.         where all_less (Leaf)         = True
  46.               all_less (Node x _ l r) = x < k && all_less l && all_less r
  47.  
  48.           all_grtr (Leaf)         = True
  49.           all_grtr (Node x _ l r) = x > k && all_grtr l && all_grtr r
  50.  
  51.     well_shaped :: Tree k v -> Bool
  52.     well_shaped (Node _ _ l r) = sl <= sr && sr <= sl + 1
  53.                                  where { sl = size l; sr = size r }
  54.     well_shaped (Leaf)         = True
  55.  
  56. Now, here's the constraint I want:
  57.     "type GoodTree k v = Tree k v SUCH THAT well_ordered && well_shaped"
  58.  
  59. It so happens that the language (Haskell) that I've used above CAN'T
  60. express that constraint.  You cannot express "is a size balanced
  61. binary search tree" in the type language.
  62.  
  63. This kind of thing is EXTREMELY common.  Part of your requirements can be
  64. expressed in the type system, but ONLY part.  The fact that your program
  65. has got through the compiler's type checking is *N*O* guarantee that you
  66. will not get a *conceptual* type error at run time.  It really is not a
  67. contest between "no type checking" (Icon) and "strong type checking"
  68. (C++, say), but subspaces of constraint space, where C++ (with ALL of its
  69. type checking) falls in the "unbelievably weak" part of constraint space.
  70.  
  71. Your interlocutor might be tempted to say "well of COURSE the compiler
  72. doesn't type check class invariants, that's what modules and encapsulation
  73. are for", to which you reply "yes, that's why Icon has them."
  74.  
  75.     "How can you protect against programmer errors in the arguments
  76.     passed during infrequently-executed invocations?"
  77.  
  78. The question is "do you need to?"  What is the evidence that the risk
  79. of such errors, for the kinds of applications you write, is high enough
  80. to spend any of your programming budget on?
  81.  
  82.     I don't think that the response (however true) that C++ has
  83.     compile-time type-checking and yet still is notorious for null
  84.     pointer errors, etc, will convince anybody.
  85.  
  86. Especially as "type-STATE checking" (null-vs-non-null, for example)
  87. *could* be handled by well understood type-checking-like approaches.
  88. As a simple example, suppose that there were two families of types:
  89.     T *x;        possibly-null pointer to T
  90.     T ^y;        non-null pointer to T
  91. and that
  92.     x = y;        was always allowed, but
  93.     y = x;        would require an explicit run-time-checking cast
  94. Then you could define
  95.     char ^strcpy(char ^dst, char const ^src) {...}
  96.  
  97.     This raises two questions in my mind regarding Icon:
  98.     
  99.     1. Should one adopt a "defensive programming style", always checking the
  100.     arguments passed to each routine?
  101.     
  102. That's an economic question.  Does the observed frequency of such errors
  103. in your code justify the development-time cost of writing such tests?
  104. What is the performance penalty of such tests?  Don't forget, the REAL
  105. checks you need include checks for well-formedness of conceptual type,
  106. not just the things you might have checked in C++.
  107.  
  108. The usual rule of thumb is "check on entry to module, not on module-internal
  109. calls", so even if you do decide to have such checks, you would by no means
  110. put them in every procedure.
  111.  
  112.     2. What work has been done on developing rigorous software-testing
  113.     methodology for Icon programs?
  114.     
  115. The usual sort of path coverage stuff (which is very very hard to achieve
  116. anyway) is blown out of the water by exceptions, which add invisible paths
  117. all over the place.  Icon backtracking does much the same thing.  However,
  118. the notion of statement coverage is still pretty useful.
  119.     
  120.